package com.xueyi.workflow.service.impl;

import com.xueyi.common.web.entity.service.impl.BaseServiceImpl;
import com.xueyi.common.core.web.result.AjaxResult;
import com.xueyi.workflow.correlate.NoneCorrelate;
import com.xueyi.workflow.domain.query.ProcessMetaQuery;
import com.xueyi.workflow.domain.dto.ProcessMetaDto;
import com.xueyi.workflow.domain.dto.WfProcessVersionDto;
import com.xueyi.workflow.domain.entity.WfProcessVersion;
import com.xueyi.workflow.manager.ProcessMetaManager;
import com.xueyi.workflow.manager.WfProcessVersionManager;
import com.xueyi.workflow.service.ProcessMetaService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xueyi.workflow.domain.dto.GraphSchema;
import com.xueyi.workflow.util.BpmnGeneratorFactory;
import org.flowable.engine.RepositoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import com.xueyi.workflow.domain.query.WfProcessVersionQuery;
import java.util.List;

@Service
public class ProcessMetaServiceImpl extends BaseServiceImpl<ProcessMetaQuery, ProcessMetaDto, NoneCorrelate, ProcessMetaManager> implements ProcessMetaService {

    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private WfProcessVersionManager wfProcessVersionManager;

    @Override
    public AjaxResult publishPublic(Long id) {
        ProcessMetaDto entity = selectById(id);
        if (entity == null) {
            return AjaxResult.error("流程不存在");
        }
        entity.setTenantId(0L);
        update(entity);
        return AjaxResult.success();
    }

    @Override
    public AjaxResult deployByGraphSchema(Long id) {
        ProcessMetaDto entity = selectById(id);
        if (entity == null || entity.getGraphSchema() == null) {
            return AjaxResult.error("流程或流程设计不存在");
        }
        try {
            // 直接使用原始的 JSON 数据，而不是转换为 GraphSchema 对象
            // 这样可以保留连线的条件表达式等字段
            String graphSchemaJson = entity.getGraphSchema();
            
            // 使用 BpmnGeneratorFactory 自动选择合适的生成器
            String bpmnXml = BpmnGeneratorFactory.generateBpmnXml(graphSchemaJson, entity.getProcessKey(), entity.getName());

            // 部署到Flowable
            var deployment = repositoryService.createDeployment()
                .addString(entity.getProcessKey() + ".bpmn20.xml", bpmnXml)
                .name(entity.getName())
                .deploy();

            // 获取当前流程的最新版本号
            Integer currentVersion = entity.getVersion() != null ? entity.getVersion() : 0;

            // 查询该流程的所有版本，找到最大版本号
            WfProcessVersionQuery versionQuery = new WfProcessVersionQuery();
            versionQuery.setProcessKey(entity.getProcessKey());
            List<WfProcessVersionDto> existingVersions = wfProcessVersionManager.selectList(versionQuery);

            Integer newVersion = 1; // 默认版本号
            if (!existingVersions.isEmpty()) {
                // 找到最大版本号并递增
                newVersion = existingVersions.stream()
                    .mapToInt(WfProcessVersionDto::getVersion)
                    .max()
                    .orElse(0) + 1;
            }

            // 检查是否有正在运行的流程实例使用旧版本
            // 这里可以添加检查逻辑，如果有正在运行的实例，可以给出警告或阻止部署

            // 保存流程版本信息到wf_process_version表（新版本）
            WfProcessVersionDto versionDto = new WfProcessVersionDto();
            versionDto.setProcessId(entity.getId());
            versionDto.setProcessKey(entity.getProcessKey());
            versionDto.setProcessName(entity.getName());
            versionDto.setVersion(newVersion);
            versionDto.setBpmnXml(bpmnXml);
            versionDto.setGraphSchema(entity.getGraphSchema());
            versionDto.setDeploymentId(deployment.getId());
            versionDto.setDeployTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
            versionDto.setCreateBy(entity.getCreateBy());
            versionDto.setStatus("0"); // 启用状态

            // 保存到数据库
            wfProcessVersionManager.insert(versionDto);

            // 更新流程元数据的版本号
            entity.setVersion(newVersion);
            update(entity);

            return AjaxResult.success("流程部署成功，版本号：" + newVersion, null);
        } catch (Exception e) {
            return AjaxResult.error("流程部署失败:" + e.getMessage());
        }
    }
}
